#include "QROHost_P.h"

struct SignalParamPacket
{
    bool isEncode;//参数是否经过了网络化编码
    QVariantList param;
};

struct CallerMessage
{
    enum Caller{
        Server,
        Client
    };

    Caller caller;
    //客户端调用的同步码
    int syncCode = 0;
    RemoteInterfaceSourceImp* channel = 0;
    //服务端的同步函数
    QRemoteObject2::InvokeCallBack callBack = {};
};

static QVariantList signalParamConvert(QROHost::Private* _P,QMetaMethod method,const SignalParamPacket& paramPacket,bool isToNet);
static bool dispatchSignal(QROHost::Private* _P,int id, int method, SignalParamPacket paramPacket,CallerMessage cm);

void QROHost::Private::onServerCall(RemoteInterfaceSourceImp* src,int id,int method,QVariantList param,int synch)
{
    CallerMessage cm;
    cm.caller = CallerMessage::Client;
    cm.syncCode = synch;
    cm.channel = src;

    bool success = dispatchSignal(this,id,method,{true,param},cm);
}

void QROHost::Private::onActiveMethod(QObject* target, int method, QVariantList param,QRemoteObject2::InvokeCallBack callBack)
{
    CallerMessage cm;
    cm.caller = CallerMessage::Server;
    cm.callBack = callBack;
    if(m_objectIdMap.contains(target))
    {
        dispatchSignal(this,m_objectIdMap[target],method,{false,param},cm);
    }
}

void QROHost::Private::onClientCallReady(RemoteInterfaceSourceImp* src,int sync,QVariant ret,bool success)
{
    auto callBack = callBackQueue.value(sync);

    if(callBack)
    {
        callBack(ret,success,"");
    }

    callBackQueue.remove(sync);
}

static bool dispatchSignal(QROHost::Private* _P,int id, int method, SignalParamPacket paramPacket,CallerMessage cm)
{
    if(!_P->m_objectDataMap.contains(id)) return false;

    auto data = _P->m_objectDataMap[id];
    auto obj = data->obj;
    auto meta = obj->metaObject();
    auto metaMethod = meta->method(method);
    if(!QRemoteObject2Meta::Instance()->allMethodData(meta->className()).contains(method)) return false;

    auto roMethod = QRemoteObject2Meta::Instance()->findMethodData(meta->className(),method);

    //计算出哪些端需要执行该函数

    bool serverExec = false,allClientExec = false,targetClientExec = false;
    RemoteInterfaceSourceImp* execChannel = NULL;

    if(roMethod.behaiovr == QRemoteObject2::ROSignalBehavior::ClientOnly)
    {
        if(cm.syncCode)//同步函数仅针对于点播
        {
            return false;
        }

        allClientExec = true;
    }
    else if(roMethod.behaiovr == QRemoteObject2::ROSignalBehavior::BroadCast)
    {
        if(cm.syncCode)//同步函数仅针对于点播
        {
            return false;
        }

        serverExec = true;
        allClientExec = true;
    }
    else if(roMethod.behaiovr == QRemoteObject2::ROSignalBehavior::ServerOnly)
    {
        serverExec = true;
    }
    else if(roMethod.behaiovr == QRemoteObject2::ROSignalBehavior::OwnerOnly)
    {
        if(cm.caller == CallerMessage::Client)
        {
            if(cm.channel->id() != _P->belongsTo(id))
            {
                //该点播请求是客户端要求的，但客户端没有占有该对象所以请求不通过
                return false;
            }
            targetClientExec = true;
            execChannel = cm.channel;
        }
        else if(cm.caller == CallerMessage::Server){
            auto owner = _P->belongsTo(id);
            if(owner)
            {
                targetClientExec = true;
                execChannel = _P->m_channels[owner]->channel;
            }
            else{
                serverExec = true;//由服务端执行
            }
        }
    }

    if(allClientExec || targetClientExec)//客户端组播或点播
    {
        auto param = signalParamConvert(_P,metaMethod,paramPacket,true);

        RemoteInterfaceSourceImp* callerChannel = NULL;

        if(cm.caller == CallerMessage::Client)
        {
            callerChannel = cm.channel;
        }

        if(allClientExec)
        {
            for(auto i:_P->m_channels)
            {
                i.second->channel->clientCall(id,method,param,0,i.second->channel == callerChannel);
            }
        }

        if(targetClientExec)
        {
            InvokeID syncId = 0;
            if(cm.caller == CallerMessage::Server && cm.callBack)
            {
                //这是由服务端发起的同步调用，需要暂存回调函数
                syncId = _P->allocInvokeID();
                _P->callBackQueue[syncId] = cm.callBack;
            }
            else if(cm.caller == CallerMessage::Client)
            {
                syncId = cm.syncCode;
            }

            //让客户端调用该方法
            execChannel->clientCall(id,method,param,syncId,execChannel == callerChannel);
        }
    }

    if(serverExec)//服务端点播
    {
        auto param = signalParamConvert(_P,metaMethod,paramPacket,false);

        auto res = invokeMetaMethod(obj,metaMethod,param);

        if(cm.caller == CallerMessage::Server)
        {
            if(cm.callBack)
            {
                cm.callBack(res,true,"");
            }
        }
        else if(cm.caller == CallerMessage::Client)
        {
            if(cm.syncCode)
            {
                _P->valueToNet(res);
                cm.channel->serverCallFinished(cm.syncCode,res,true);
            }
        }
    }

    return true;
}

//对应输出的端进行参数转换
static QVariantList signalParamConvert(QROHost::Private* _P,QMetaMethod method,const SignalParamPacket& paramPacket,bool isToNet){
    auto ret = paramPacket.param;
    if(paramPacket.isEncode && !isToNet)
    {
        auto paramCount = method.parameterCount();
        for(int i = 0;i<method.parameterType(paramCount);i++)
        {
            auto targetType = method.parameterType(i);
            _P->valueFromNet(ret[i],targetType);
        }
    }
    else if(!paramPacket.isEncode && isToNet)
    {
        for(auto &i:ret)
        {
            _P->valueToNet(i);
        }
    }

    return ret;
}
